home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / Apple Game Sprockets / More Sprocket Examples 1.0 / DroneZone Sources / DZGame.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-12  |  12.1 KB  |  515 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    File:        DZGame.c
  3.  *
  4.  *    Contents:    Handles the game play.
  5.  *
  6.  *    Copyright © 1996 Apple Computer, Inc.
  7.  */
  8.  
  9. #include <assert.h>
  10. #include <string.h>
  11.  
  12. #include <Events.h>
  13. #include <Fonts.h>
  14. #include <QDOffscreen.h>
  15. #include <Timer.h>
  16. #include <Types.h>
  17.  
  18. #include <QD3D.h>
  19. #include <QD3DGeometry.h>
  20. #include <QD3DMath.h>
  21. #include <QD3DSet.h>
  22.  
  23. #include "SoundSprocket.h"
  24.  
  25. #include "DZDisplay.h"
  26. #include "DZDrone.h"
  27. #include "DZGame.h"
  28. #include "DZInput.h"
  29. #include "DZSound.h"
  30. #include "DZSpace.h"
  31.  
  32. #ifndef ONE_DRONE
  33.     #define ONE_DRONE        0
  34. #endif
  35.  
  36.  
  37.  
  38. #define DEFAULT_INTERVAL    0.05        // Initial frame rate -- just a guess
  39. #define MAX_INTERVAL        0.25        // Limit on seconds per frame
  40.  
  41. #define INV_SQRT_TWO        0.707
  42.  
  43. #define AXIS_ROTATE_RATE    3.0            // Radians per second for full joystick throw
  44.  
  45.  
  46. enum {
  47.     #if ONE_DRONE
  48.         kGameAutoDroneCount = 1            // Number of autopilot drones
  49.     #else
  50.         kGameAutoDroneCount = 4            // Number of autopilot drones
  51.     #endif
  52. };
  53.  
  54.  
  55. float                        gGameInterval            = DEFAULT_INTERVAL;
  56. float                        gGameFramesPerSecond    = 1.0/DEFAULT_INTERVAL;
  57.  
  58. static TGameState            gGameState                = kGameState_Stopped;
  59.  
  60. static unsigned long        gGameTime                = 0;        // Last frame time
  61.  
  62. static Boolean                gGameHUDVisible            = true;
  63.  
  64. static TDroneObject            gGameSelfDrone            = NULL;
  65.  
  66. static GWorldPtr            gGameFPSGWorld            = NULL;
  67. static TQ3GeometryObject    gGameFPSMarker            = NULL;
  68. static TQ3MarkerData        gGameFPSMarkerData;
  69. static Boolean                gGameFPSVisible            = false;
  70.  
  71. static TQ3GeometryObject    gGameCrossHairs            = NULL;
  72. static unsigned long        gGameCrossHairsData[32]    = {
  73.     0x00000000, 0x00000000, 0x00000000, 0x00000000,
  74.     0x00000000, 0x00010000, 0x00000000, 0x00010000,
  75.     0x00000000, 0x00054000, 0x00101000, 0x00228800,
  76.     0x00082000, 0x00400400, 0x00101000, 0x05400540,
  77.     0x00101000, 0x00400400, 0x00082000, 0x00228800,
  78.     0x00101000, 0x00054000, 0x00000000, 0x00010000,
  79.     0x00000000, 0x00010000, 0x00000000, 0x00000000,
  80.     0x00000000, 0x00000000, 0x00000000, 0x00000000
  81. };
  82.  
  83.  
  84. /* =============================================================================
  85.  *        Game_Init (external)
  86.  *
  87.  *    Initializes the game stuff.
  88.  * ========================================================================== */
  89. void Game_Init(
  90.     void)
  91. {
  92.     Rect                bounds;
  93.     PixMapHandle        pixMapHandle;
  94.     CGrafPtr            savePort;
  95.     GDHandle            saveGDevice;
  96.     TQ3MarkerData        markerData;
  97.     TQ3ColorRGB            color;
  98.     
  99.     // Set up the 3D sound listener
  100.     Sound_GetListener();
  101.     
  102.     // Create the FPS marker
  103.     bounds.top    = 0;
  104.     bounds.left   = 0;
  105.     bounds.bottom = 12;
  106.     bounds.right  = 31;
  107.     
  108.     gGameFPSGWorld = NULL;
  109.     NewGWorld(&gGameFPSGWorld, 1, &bounds, NULL, NULL, 0);
  110.     assert(gGameFPSGWorld != NULL);
  111.     
  112.     LockPixels(gGameFPSGWorld->portPixMap);
  113.     
  114.     GetGWorld(&savePort, &saveGDevice);
  115.     SetGWorld(gGameFPSGWorld, NULL);
  116.     
  117.     TextFont(geneva);
  118.     TextSize(10);
  119.     
  120.     EraseRect(&gGameFPSGWorld->portRect);
  121.     
  122.     SetGWorld(savePort, saveGDevice);
  123.     
  124.     pixMapHandle = GetGWorldPixMap(gGameFPSGWorld);
  125.     
  126.     gGameFPSMarkerData.location.x            = 0.0;
  127.     gGameFPSMarkerData.location.y            = 0.0;
  128.     gGameFPSMarkerData.location.z            = 0.0;
  129.     gGameFPSMarkerData.xOffset                = -(bounds.left+bounds.right+1 >> 1);
  130.     gGameFPSMarkerData.yOffset                = -(bounds.top+bounds.bottom+1 >> 1);
  131.     gGameFPSMarkerData.bitmap.image            = (unsigned char*) GetPixBaseAddr(pixMapHandle);
  132.     gGameFPSMarkerData.bitmap.width            = bounds.right-bounds.left;
  133.     gGameFPSMarkerData.bitmap.height        = bounds.bottom-bounds.top;
  134.     gGameFPSMarkerData.bitmap.rowBytes        = (*pixMapHandle)->rowBytes & 0x00003FFF;
  135.     gGameFPSMarkerData.bitmap.bitOrder        = kQ3EndianBig;
  136.     gGameFPSMarkerData.markerAttributeSet    = Q3AttributeSet_New();
  137.     assert(gGameFPSMarkerData.markerAttributeSet != NULL);
  138.     
  139.     color.r = 1.0;
  140.     color.g = 1.0;
  141.     color.b = 0.4;
  142.     
  143.     Q3AttributeSet_Add(gGameFPSMarkerData.markerAttributeSet, kQ3AttributeTypeDiffuseColor, &color);
  144.     
  145.     gGameFPSMarker = Q3Marker_New(&gGameFPSMarkerData);
  146.     
  147.     // Create the crosshairs
  148.     markerData.location.x            = 0.0;
  149.     markerData.location.y            = 0.0;
  150.     markerData.location.z            = 0.0;
  151.     markerData.xOffset                = -15;
  152.     markerData.yOffset                = -15;
  153.     markerData.bitmap.image            = (unsigned char*) gGameCrossHairsData;
  154.     markerData.bitmap.width            = 31;  //• SHOULD BE 32, BUT TO GET AROUND A APPLE QD3D ACCEL CARD DRIVER BUG...
  155.     markerData.bitmap.height        = 32;
  156.     markerData.bitmap.rowBytes        = 4;
  157.     markerData.bitmap.bitOrder        = kQ3EndianBig;
  158.     markerData.markerAttributeSet    = Q3AttributeSet_New();
  159.     assert(markerData.markerAttributeSet != NULL);
  160.     
  161.     color.r = 1.0;
  162.     color.g = 1.0;
  163.     color.b = 0.4;
  164.     
  165.     Q3AttributeSet_Add(markerData.markerAttributeSet, kQ3AttributeTypeDiffuseColor, &color);
  166.     
  167.     gGameCrossHairs = Q3Marker_New(&markerData);
  168.     
  169.     Q3Object_Dispose(markerData.markerAttributeSet);
  170.     markerData.markerAttributeSet = NULL;
  171. }
  172.  
  173.  
  174. /* =============================================================================
  175.  *        Game_Exit (external)
  176.  *
  177.  *    Prepares for exit.
  178.  * ========================================================================== */
  179. void Game_Exit(
  180.     void)
  181. {
  182.     if (gGameFPSMarker != NULL)
  183.     {
  184.         Q3Object_Dispose(gGameFPSMarker);
  185.         gGameFPSMarker = NULL;
  186.     }
  187.     
  188.     if (gGameCrossHairs != NULL)
  189.     {
  190.         Q3Object_Dispose(gGameCrossHairs);
  191.         gGameCrossHairs = NULL;
  192.     }
  193. }
  194.  
  195.  
  196. /* =============================================================================
  197.  *        Game_GetState (external)
  198.  *
  199.  *    Returns the game state.
  200.  * ========================================================================== */
  201. TGameState Game_GetState(
  202.     void)
  203. {
  204.     return gGameState;
  205. }
  206.  
  207.  
  208. /* =============================================================================
  209.  *        Game_SetState (external)
  210.  *
  211.  *    Changes the game state.
  212.  * ========================================================================== */
  213. void Game_SetState(
  214.     TGameState            inGameState)
  215. {
  216.     TGameState            prevGameState;
  217.     TDroneObject        drone;
  218.     int                    droneNum;
  219.     
  220.     if (gGameState != inGameState)
  221.     {
  222.         prevGameState = gGameState;
  223.         gGameState = inGameState;
  224.         
  225.         switch (gGameState)
  226.         {
  227.             case kGameState_Playing:
  228.                 // Begin Playing
  229.                 if (prevGameState == kGameState_Stopped)
  230.                 {
  231.                     gGameSelfDrone = SelfDrone_New();
  232.                     
  233.                     // Create some automatic drones
  234.                     for (droneNum = 0; droneNum < kGameAutoDroneCount; droneNum++)
  235.                     {
  236.                         AutoDrone_New(gGameSelfDrone);
  237.                     }
  238.                 }
  239.                 
  240.                 Display_DrawContents();
  241.                 Input_Activate(true);
  242.             break;
  243.             
  244.             case kGameState_Paused:
  245.                 // From Playing to Paused
  246.                 assert(prevGameState != kGameState_Stopped);
  247.                 
  248.                 Game_Silence();
  249.                 Display_DrawContents();
  250.                 Input_Activate(false);
  251.             break;
  252.             
  253.             case kGameState_Stopped:
  254.                 // From Playing or Paused to Stopped
  255.                 while ((drone = Drone_Next(NULL)) != NULL)
  256.                 {
  257.                     Drone_Dispose(drone);
  258.                 }
  259.                 
  260.                 gGameSelfDrone = NULL;
  261.                 
  262.                 Display_DrawContents();
  263.                 Input_Activate(false);
  264.             break;
  265.         }
  266.     }
  267. }
  268.  
  269.  
  270. /* =============================================================================
  271.  *        Game_Process (external)
  272.  *
  273.  *    Handles idle time by moving the game ahead one time step.  Only called if
  274.  *    the game is in "play" state.
  275.  * ========================================================================== */
  276. void Game_Process(
  277.     void)
  278. {
  279.     UnsignedWide        wide;
  280.     unsigned long        now;
  281.     Str15                str;
  282.     CGrafPtr            savePort;
  283.     GDHandle            saveGDevice;
  284.     TDroneObject        drone;
  285.     TDroneObject        next;
  286.     TQ3Point3D            position;
  287.     TQ3Vector3D            direction;
  288.     TQ3Vector3D            up;
  289.     TQ3Matrix4x4        matrix;
  290.     float                xAxis;
  291.     float                yAxis;
  292.     Boolean                ok;
  293.     UInt32                count;
  294.     
  295.     // Find the frame rate
  296.     Microseconds(&wide);
  297.     now = wide.lo;
  298.     
  299.     if (gGameTime != 0)
  300.     {
  301.         // Find the interval for the last frame
  302.         gGameInterval = 0.000001*(now-gGameTime);
  303.         
  304.         // Limit frame rate to a resonable number
  305.         if (gGameInterval > MAX_INTERVAL)
  306.         {
  307.             gGameInterval = MAX_INTERVAL;
  308.         }
  309.         
  310.         // Find corresponding frames per second
  311.         gGameFramesPerSecond = 1.0/gGameInterval;
  312.     }
  313.     
  314.     gGameTime = now;
  315.     
  316.     // Update the FPS marker
  317.     if (gGameFPSVisible)
  318.     {
  319.         sprintf((char*) str, "x%.1f", gGameFramesPerSecond);
  320.         str[0] = strlen((char*) str) - 1;
  321.         
  322.         GetGWorld(&savePort, &saveGDevice);
  323.         SetGWorld(gGameFPSGWorld, NULL);
  324.         
  325.         EraseRect(&gGameFPSGWorld->portRect);
  326.         
  327.         MoveTo(gGameFPSGWorld->portRect.left+gGameFPSGWorld->portRect.right-StringWidth(str) >> 1, 10);
  328.         DrawString(str);
  329.         
  330.         SetGWorld(savePort, saveGDevice);
  331.         
  332.         Q3Marker_SetBitmap(gGameFPSMarker, &gGameFPSMarkerData.bitmap);
  333.     }
  334.     
  335.     // Get and process state-based inputs
  336.     Input_GetState(&xAxis, &yAxis);
  337.     
  338.     SelfDrone_Turn(
  339.             gGameSelfDrone,
  340.             xAxis*gGameInterval*AXIS_ROTATE_RATE,
  341.             yAxis*gGameInterval*AXIS_ROTATE_RATE);
  342.     
  343.     // Get and process input events
  344.     ok = true;
  345.     do
  346.     {
  347.         switch (Input_GetEvent())
  348.         {
  349.             case kInputEvent_None:
  350.                 // No more input events to process
  351.                 ok = false;
  352.             break;
  353.             
  354.             case kInputEvent_Fire:
  355.                 // Fire button
  356.                 Drone_Fire(gGameSelfDrone);
  357.             break;
  358.             
  359.             case kInputEvent_Pause:
  360.                 // Toggle paused/play state
  361.                 switch (gGameState)
  362.                 {
  363.                     case kGameState_Playing:
  364.                         Game_SetState(kGameState_Paused);
  365.                     break;
  366.                     
  367.                     case kGameState_Paused:
  368.                         Game_SetState(kGameState_Playing);
  369.                     break;
  370.                     
  371.                     case kGameState_Stopped:
  372.                         // do nothing
  373.                     break;
  374.                 }
  375.             break;
  376.             
  377.             case kInputEvent_ShowHUD:
  378.                 // Toggle HMD display
  379.                 gGameHUDVisible = !gGameHUDVisible;
  380.             break;
  381.             
  382.             case kInputEvent_ShowFPS:
  383.                 // Toggle FPS display
  384.                 gGameFPSVisible = !gGameFPSVisible;
  385.             break;
  386.         }
  387.     }
  388.     while (ok);
  389.     
  390.     // Move all the drones, mark any to be deleted
  391.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  392.     {
  393.         Drone_Move(drone);
  394.     }
  395.     
  396.     // Delete the marked drones
  397.     drone = Drone_Next(NULL);
  398.     while (drone != NULL)
  399.     {
  400.         next = Drone_Next(drone);
  401.         
  402.         if (Drone_GetMark(drone))
  403.         {
  404.             Drone_Dispose(drone);
  405.         }
  406.         
  407.         drone = next;
  408.     }
  409.     
  410.     // Move the viewer to follow the self drone
  411.     Drone_GetPosition(gGameSelfDrone, &position);
  412.     Drone_GetDirection(gGameSelfDrone, &direction);
  413.     Drone_GetUp(gGameSelfDrone, &up);
  414.     
  415.     Display_SetViewerPosition(&position, &direction, &up);
  416.     
  417.     // Move the listener to follow the self drone
  418.     Drone_GetMatrix(gGameSelfDrone, &matrix);
  419.     SSpListener_SetTransform(Sound_GetListener(), &matrix);
  420.     
  421.     // Change the localized sounds
  422.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  423.     {
  424.         Drone_UpdateSound(drone);
  425.     }
  426.     
  427.     // Time to retire?
  428.     
  429.     // NOTE: This is not the best way to determine if the game is done.  We
  430.     // should probably ask each drone if it thinks the game should continue.
  431.     // Only AutoDrones would respond yes.  Then we'd "or" the results.
  432.     
  433.     count = 0;
  434.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  435.     {
  436.         count += 1;
  437.     }
  438.     
  439.     if (count == 1)
  440.     {
  441.         // Only the autodrone is left -- time to quit
  442.         Game_SetState(kGameState_Stopped);
  443.     }
  444. }
  445.  
  446.  
  447. /* =============================================================================
  448.  *        Game_Submit (external)
  449.  *
  450.  *    Submits all the 3D geometry of the game.
  451.  * ========================================================================== */
  452. void Game_Submit(
  453.     TQ3ViewObject        inView)
  454. {
  455.     TDroneObject        drone;
  456.     TQ3Point3D            position;
  457.     TQ3Vector3D            direction;
  458.     TQ3Vector3D            up;
  459.     TQ3Vector3D            v;
  460.     TQ3Point3D            markerPosition;
  461.     
  462.     assert(inView != NULL);
  463.     
  464.     // Submit the drones
  465.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  466.     {
  467.         Drone_Submit(drone, gGameHUDVisible, inView);
  468.     }
  469.     
  470.     // Get information about the camera position
  471.     Drone_GetPosition(gGameSelfDrone, &position);
  472.     Drone_GetDirection(gGameSelfDrone, &direction);
  473.     Drone_GetUp(gGameSelfDrone, &up);
  474.     
  475.     // Submit the spacejunk
  476.     Space_Submit(inView, &position, &direction);
  477.     
  478.     // Submit the FPS marker
  479.     if (gGameFPSVisible)
  480.     {
  481.         Q3Point3D_Vector3D_Add(&position, &direction, &markerPosition);
  482.         Q3Vector3D_Scale(&up, -0.6, &v);
  483.         Q3Point3D_Vector3D_Add(&markerPosition, &v, &markerPosition);
  484.         Q3Marker_SetPosition(gGameFPSMarker, &markerPosition);
  485.         Q3Object_Submit(gGameFPSMarker, inView);
  486.     }
  487.     
  488.     // Submit the crosshairs
  489.     if (gGameHUDVisible)
  490.     {
  491.         Q3Point3D_Vector3D_Add(&position, &direction, &markerPosition);
  492.         Q3Marker_SetPosition(gGameCrossHairs, &markerPosition);
  493.         Q3Object_Submit(gGameCrossHairs, inView);
  494.     }
  495. }
  496.  
  497.  
  498. /* =============================================================================
  499.  *        Game_Silence (external)
  500.  *
  501.  *    Stops all sounds.
  502.  * ========================================================================== */
  503. void Game_Silence(
  504.     void)
  505. {
  506.     TDroneObject        drone;
  507.     
  508.     for (drone = Drone_Next(NULL); drone != NULL; drone = Drone_Next(drone))
  509.     {
  510.         Drone_Silence(drone);
  511.     }
  512. }
  513.  
  514.  
  515.